home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 June / Macworld (1999-06).dmg / Shareware World / Info / For Developers / MacZoop2.0.sea / MacZoop2.0 / Required Classes / ZObjectArray.cpp < prev    next >
Text File  |  1998-12-17  |  10KB  |  368 lines

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            MacZoop - "the framework for the rest of us"         
  5. *
  6. *
  7. *
  8. *            ZObjectArray.cpp    -- a container for objects (template class)
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1996, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21.  
  22. #include    "ZObjectArray.h"
  23. #include    "ZErrors.h"
  24. #include    "ZDefines.h"
  25. #include    "ZStream.h"
  26.  
  27. /*---------------------------------***  CONSTRUCTOR  ***---------------------------------*/
  28.  
  29. template <class T> ZObjectArray<T>::ZObjectArray()
  30.     : ZArray( sizeof(T*) )
  31. {
  32.     classID = CLASS_ZObjectArray;
  33.     
  34.     // we manipulate our handle via <o> rather than <a> so we can take advantage
  35.     // of direct register copies, etc for maximum performance, which is what this
  36.     // class is all about (it avoids BlockMove).
  37.     
  38.     o = (T***) a;
  39. }
  40.  
  41. /*----------------------------------***  GETOBJECT  ***----------------------------------*/
  42. /*    
  43. return the object at <index>
  44. -----------------------------------------------------------------------------------------*/
  45.  
  46. template <class T> T*    ZObjectArray<T>::GetObject( const long index )
  47. {
  48.     // gets the item at position <index> in the array. Index is one-based.
  49.     
  50.     if ((index < 1) || (index > numElements))
  51.         FailOSErr( kIndexOutOfRangeErr );
  52.         
  53.     return ((*o)[index - 1]);
  54. }
  55.  
  56.  
  57. /*--------------------------------***  DELETEOBJECT  ***---------------------------------*/
  58. /*    
  59. delete the object at <index> from the array. Does not dispose of the object itself
  60. -----------------------------------------------------------------------------------------*/
  61.  
  62. template <class T> void    ZObjectArray<T>::DeleteObject(T* item)
  63. {
  64.     long    index;
  65.     
  66.     index = FindIndex( item );
  67.     
  68.     if (index > 0)
  69.         DeleteItem ( index );
  70. }
  71.  
  72.  
  73. /*---------------------------------***  DISPOSEALL  ***----------------------------------*/
  74. /*    
  75. disposes of all of the objects in the array
  76. -----------------------------------------------------------------------------------------*/
  77.  
  78. template <class T> void    ZObjectArray<T>::DisposeAll()
  79. {
  80.     // calls ForgetObject for every object in the array, then forces the array empty. Since
  81.     // it is possible for ForgetObject to modify this array, we iterate in reverse order.
  82.     
  83.     long    i = numElements;
  84.     T*        p;
  85.     
  86.     while(i--)
  87.     {
  88.         p = (*o)[i];
  89.         
  90.         if (p)
  91.             ForgetObject(p);
  92.     }
  93.  
  94.     SetHandleSize( a, 0 );
  95.     numElements = 0;
  96.     physicalBlks = 0;
  97. }
  98.  
  99.  
  100. /*----------------------------------***  DOFOREACH  ***----------------------------------*/
  101. /*    
  102. calls the grovelling function for every object in the array
  103. -----------------------------------------------------------------------------------------*/
  104.  
  105. template <class T> void    ZObjectArray<T>::DoForEach( IteratorProcPtr aProc, const long ref )
  106. {
  107.     // calls the grovelling function for every object in the array.
  108.     
  109.     if (aProc && (numElements > 0))
  110.     {
  111.         long    i = numElements;
  112.         
  113.         while(i)
  114.             (*aProc)((*o)[--i] , ref);
  115.     }
  116. }
  117.  
  118.  
  119. /*-----------------------------------***  CONTAINS  ***----------------------------------*/
  120. /*    
  121. returns TRUE if the object can be found in the array
  122. -----------------------------------------------------------------------------------------*/
  123.  
  124. template <class T> Boolean    ZObjectArray<T>::Contains(T* item)
  125. {
  126.     return (FindIndex( item ) > 0);
  127. }
  128.  
  129.  
  130. /*--------------------------------***  SETARRAYITEM  ***---------------------------------*/
  131. /*    
  132. overrides the inherited method to store objects in the list avoiding BlockMove().
  133. -----------------------------------------------------------------------------------------*/
  134.  
  135. template <class T> void    ZObjectArray<T>::SetArrayItem( void* item, const long index )
  136. {
  137.     if ((index < 1) || (index > numElements))
  138.         FailOSErr( kIndexOutOfRangeErr );
  139.         
  140.     (*o)[index - 1] = (T*) item;
  141. }
  142.  
  143.  
  144. /*--------------------------------***  GETARRAYITEM  ***---------------------------------*/
  145. /*    
  146. overrides the inherited method to obtain objects in the list avoiding BlockMove().
  147. -----------------------------------------------------------------------------------------*/
  148.  
  149. template <class T> void    ZObjectArray<T>::GetArrayItem( void* item, const long index )
  150. {
  151.     if ((index < 1) || (index > numElements))
  152.         FailOSErr( kIndexOutOfRangeErr );
  153.         
  154.     *(T**)item = ((*o)[index - 1]);
  155. }
  156.  
  157.  
  158. /*-----------------------------***  CONCATENATEARRAY  ***--------------------------------*/
  159. /*    
  160. joins another similar array to the end of this one. The source array must be of the same
  161. type and is uaffected by the copy. Since the arrays contain object refs, note that both
  162. arrays will have the same objects in them after this, so take care.
  163. -----------------------------------------------------------------------------------------*/
  164.  
  165. template <class T> void    ZObjectArray<T>::ConcatenateArray( ZObjectArray<T>* anArray )
  166. {
  167.     ZArray::ConcatenateArray((ZArray*) anArray );
  168. }
  169.  
  170.  
  171.  
  172.  
  173. /*----------------------------------***  FINDINDEX  ***----------------------------------*/
  174. /*    
  175. return the index of the object, or zero if not found.
  176. -----------------------------------------------------------------------------------------*/
  177.  
  178. template <class T> long    ZObjectArray<T>::FindIndex(T* item)
  179. {
  180.     if ( numElements < 1 )
  181.         return 0;
  182.         
  183.     long        i = 0;
  184.     Boolean        found = FALSE;
  185.     
  186.     do
  187.     {
  188.         if ((*o)[i] == item)
  189.         {
  190.             found = TRUE;
  191.             break;
  192.         }    
  193.     }
  194.     while( ++i < numElements );
  195.  
  196.     return ( found? i + 1 : 0 );
  197. }
  198.  
  199.  
  200. /*-------------------------------***  INSERTSORTEDITEM  ***------------------------------*/
  201. /*    
  202. inserts into the array at the correct place according to sort order
  203. -----------------------------------------------------------------------------------------*/
  204.  
  205. template <class T> long    ZObjectArray<T>::InsertSortedItem( void* item, SortCmpProcPtr compareProc, const long ref )
  206. {
  207.     T*        itemB;
  208.     short    rel;
  209.     long    pos = BFindIndex( &item, compareProc, ref );
  210.     
  211.     // <pos> represents the NEAREST item, but we don't know if we need to insert
  212.     // before or after this item, so we need to do one more compare
  213.     
  214.     if ( pos > 0 )
  215.     {
  216.         GetArrayItem( &itemB, pos );
  217.         
  218.         rel = (*compareProc)( &item, &itemB, ref );
  219.         
  220.         if ( rel > 0 )
  221.             pos++;
  222.     }
  223.         
  224.     if (( pos > numElements ) || ( pos == 0 ))
  225.     {
  226.         AppendItem( item );
  227.         pos = numElements;
  228.     }
  229.     else
  230.         InsertItem( item, pos );
  231.         
  232.     return pos;
  233. }
  234.  
  235.  
  236. /*-------------------------------------***  SWAP  ***------------------------------------*/
  237. /*    
  238. swaps the items at indices a and b- can be used within sorts, etc
  239. -----------------------------------------------------------------------------------------*/
  240.  
  241. template <class T> void    ZObjectArray<T>::Swap( const long itema, const long itemb )
  242. {
  243.     register T* temp;
  244.     
  245.     if ((itema < 1) ||
  246.         (itema > numElements) ||
  247.         (itemb < 1) ||
  248.         (itemb > numElements))
  249.         FailOSErr( kIndexOutOfRangeErr );
  250.         
  251.     temp = GetObject( itema );
  252.     
  253.     (*o)[itema - 1] = (*o)[itemb - 1];
  254.     (*o)[itemb - 1] = temp;
  255. }
  256.  
  257.  
  258. /*-----------------------------------***  MOVEITEM  ***----------------------------------*/
  259. /*    
  260. moves the object at index <curIndex> to the index <newIndex>, displacing other items
  261. as needed. Completely overrides the ZArray method for better efficiency and to eliminate
  262. "pointer to pointer to object" dereferencing difficulties.
  263. -----------------------------------------------------------------------------------------*/
  264.  
  265. template <class T> void    ZObjectArray<T>::MoveItem( const long curIndex, const long newIndex )
  266. {
  267.     register T*    temp;
  268.     
  269.     if ((curIndex < 1)                 ||
  270.         (curIndex > numElements)     ||
  271.         (newIndex < 1)                 ||
  272.         (newIndex > numElements))
  273.         FailOSErr( kIndexOutOfRangeErr );
  274.     
  275.     // don't do anything if indices the same (not an error)
  276.     
  277.     if ( curIndex != newIndex )
  278.     {    
  279.         temp = GetObject( curIndex );
  280.         
  281.         DeleteItem( curIndex );
  282.         InsertItem( temp, newIndex );
  283.         
  284.         SendMessage( msgArrayItemMoved, (void*) newIndex );
  285.     }
  286. }
  287.  
  288. /*---------------------------------***  MOVETOFRONT  ***---------------------------------*/
  289. /*    
  290. moves the object at index <curIndex> to the front of the list (1)
  291. -----------------------------------------------------------------------------------------*/
  292.  
  293. template <class T> void    ZObjectArray<T>::MoveToFront( const long index )
  294. {
  295.     MoveItem( index, 1 );
  296. }
  297.  
  298. /*----------------------------------***  MOVETOBACK  ***---------------------------------*/
  299. /*    
  300. moves the object at index <curIndex> to the back of the list (n)
  301. -----------------------------------------------------------------------------------------*/
  302.  
  303. template <class T> void    ZObjectArray<T>::MoveToBack( const long index )
  304. {
  305.     MoveItem( index, CountItems());
  306. }
  307.  
  308.  
  309. /*-------------------------------***  WRITETOSTREAM  ***--------------------------------*/
  310. /*    
  311. write entire array object to stream. Since this array holds objects, we save each one
  312. as an object reference, not the same way that ZArray works. Note that <T> must be derived
  313. from ZObject and registered with <gClasses> for this to work, but when it does work the
  314. power this unleashes is astonishing! 
  315. ----------------------------------------------------------------------------------------*/
  316.  
  317. template <class T> void    ZObjectArray<T>::WriteToStream( ZStream* aStream )
  318. {
  319.     ZComrade::WriteToStream( aStream );
  320.     
  321.     register long    i;
  322.     
  323.     // count of objects to follow:
  324.     
  325.     aStream->WriteLong( numElements );
  326.     
  327.     // write the object references as needed:
  328.     
  329.     for ( i = 1; i <= numElements; i++ )
  330.         aStream->WriteObject( GetObject( i ));
  331. }
  332.  
  333. /*------------------------------***  READFROMSTREAM  ***--------------------------------*/
  334. /*    
  335. read entire array back from stream. This refills the array with objects built from the
  336. stream. These objects are equivalent to the ones saved in the stream originally, and
  337. have the same type and function.
  338. ----------------------------------------------------------------------------------------*/
  339.  
  340.  
  341. template <class T> void    ZObjectArray<T>::ReadFromStream( ZStream* aStream )
  342. {
  343.     ZComrade::ReadFromStream( aStream );
  344.     
  345.     register T*        temp;
  346.     register long    i, numObjects;
  347.     
  348.     aStream->ReadLong( &numObjects );
  349.     
  350.     // size the storage handle as needed to hold this many objects:
  351.     
  352.     if ( numElements != numObjects )
  353.     {
  354.         SetHandleSize( a, numObjects * blkSize );
  355.         FailMemError();
  356.         
  357.         numElements = numObjects;
  358.     }
  359.     
  360.     for ( i = 1; i <= numObjects; i++ )
  361.     {
  362.         temp = (T*) aStream->ReadObject();
  363.         SetArrayItem( temp, i );
  364.     }
  365. }
  366.  
  367.  
  368.